#ifndef __EVENTLOOP_H__
#define __EVENTLOOP_H__

#include <sys/epoll.h>
#include <vector>
#include <map>
#include <memory>
#include <functional>
#include <mutex>

using std::function;
using std::vector;
using std::map;
using std::shared_ptr;
using std::mutex;
using std::lock_guard;

class Acceptor;
class TcpConnection;

class EventLoop
{
public:
	EventLoop(Acceptor & acceptor);

	~EventLoop();

	void loop();

	void unloop();

	void setNewConnectionCallBack(function<void(const shared_ptr<TcpConnection>&)>&&callBack);
	void setMessageCallBack(function<void(const shared_ptr<TcpConnection>&)>&&callBack);
	void setCloseCallBack(function<void(const shared_ptr<TcpConnection>&)>&&callBack);

	void handleRead();

	void wakeUp();

	int createEventFd();

	void doPendingFunctors();

	void runInLoop(function<void()> && callBack);

private:
	void waitEpollFd();

	void handleNewConnection();
	
	void handleMessage(int fd);

	int createEpollFd();

	void addEpollReadFd(int fd);

	void delEpollReadFd(int fd);

private:
	int _epfd;

	vector<struct epoll_event> _eventList;

	bool _isLooping;

	Acceptor & _acceptor;

	map<int,shared_ptr<TcpConnection>> _conns;

	function<void(const shared_ptr<TcpConnection>&)> _callBackNewConnection;
	function<void(const shared_ptr<TcpConnection>&)> _callBackMessage;
	function<void(const shared_ptr<TcpConnection>&)> _callBackClose;

	int _eventFd;

	vector<function<void()>> _pendings;

	mutex _mutex;
};

#endif
